package com.luom.fsp.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.luom.fsp.common.ErrorCode;
import com.luom.fsp.constant.CommonConstant;
import com.luom.fsp.exception.BusinessException;
import com.luom.fsp.exception.ThrowUtils;
import com.luom.fsp.mapper.CartMapper;
import com.luom.fsp.mapper.OrderMapper;
import com.luom.fsp.model.dto.order.*;
import com.luom.fsp.model.entity.*;
import com.luom.fsp.model.enums.*;
import com.luom.fsp.model.vo.*;
import com.luom.fsp.service.*;
import com.luom.fsp.utils.AsyncMessageSender;
import com.luom.fsp.utils.SqlUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.luom.fsp.constant.RedisConstant.*;

/**
 * 订单服务实现
 */
@Service
@Slf4j
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {

    @Resource
    private UserService userService;

    @Resource
    private AddressService addressService;

    @Resource
    private ProductService productService;

    @Resource
    private ProductSKUService productSKUService;

    @Resource
    private UserCouponService userCouponService;

    @Resource
    private CouponService couponService;

    @Resource
    private OrderMapper orderMapper;

    @Resource
    private CartService cartService;

    @Resource
    private CartMapper cartMapper;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private AsyncMessageSender asyncMessageSender;

    /**
     * 校验数据
     *
     * @param order
     * @param add   对创建的数据进行校验
     */
    @Override
    public void validOrder(Order order, boolean add) {
        ThrowUtils.throwIf(order == null, ErrorCode.PARAMS_ERROR);

        Long id = order.getId();
        Long addressId = order.getAddressId();
        Long skuId = order.getSkuId();
        Integer quantity = order.getQuantity();

        // 创建数据时，参数不能为空
        if (add) {
            ThrowUtils.throwIf(ObjectUtils.isEmpty(addressId), ErrorCode.PARAMS_ERROR, "收货地址不能为空");
            ThrowUtils.throwIf(ObjectUtils.isEmpty(skuId), ErrorCode.PARAMS_ERROR, "商品不能为空");
            ThrowUtils.throwIf(ObjectUtils.isEmpty(quantity), ErrorCode.PARAMS_ERROR, "商品数量不能为空");

        }
        // 修改数据时，有参数则校验
        /*if (StringUtils.isNotBlank(title)) {
            ThrowUtils.throwIf(title.length() > 80, ErrorCode.PARAMS_ERROR, "标题过长");
        }*/
    }

    /**
     * 获取查询条件
     *
     * @param orderQueryRequest
     * @return
     */
    @Override
    public QueryWrapper<Order> getQueryWrapper(OrderQueryRequest orderQueryRequest) {
        QueryWrapper<Order> queryWrapper = new QueryWrapper<>();
        if (orderQueryRequest == null) {
            return queryWrapper;
        }
        Long id = orderQueryRequest.getId();
        Long userId = orderQueryRequest.getUserId();
        Long addressId = orderQueryRequest.getAddressId();
        Long skuId = orderQueryRequest.getSkuId();
        String orderStatus = orderQueryRequest.getOrderStatus();
        String paymentStatus = orderQueryRequest.getPaymentStatus();
        String sortField = orderQueryRequest.getSortField();
        String sortOrder = orderQueryRequest.getSortOrder();

        // 精确查询
        queryWrapper.eq(ObjectUtils.isNotEmpty(id), "id", id);
        queryWrapper.eq(ObjectUtils.isNotEmpty(userId), "userId", userId);
        queryWrapper.eq(ObjectUtils.isNotEmpty(addressId), "addressId", addressId);
        queryWrapper.eq(ObjectUtils.isNotEmpty(skuId), "skuId", skuId);
        queryWrapper.eq(ObjectUtils.isNotEmpty(orderStatus), "orderStatus", orderStatus);
        queryWrapper.eq(ObjectUtils.isNotEmpty(paymentStatus), "paymentStatus", paymentStatus);
        // 排序规则
        queryWrapper.orderBy(SqlUtils.validSortField(sortField),
                sortOrder.equals(CommonConstant.SORT_ORDER_ASC),
                sortField);
        return queryWrapper;
    }

    /**
     * 获取订单封装
     *
     * @param order
     * @param request
     * @return
     */
    @Override
    public OrderVO getOrderVO(Order order, HttpServletRequest request) {
        // 对象转封装类
        OrderVO orderVO = OrderVO.objToVo(order);

        // 关联查询用户信息
        User user = userService.getById(order.getUserId());
        if (user != null) {
            UserVO userVO = new UserVO();
            BeanUtil.copyProperties(user, userVO);
            orderVO.setUser(userVO);
        }

        // 关联查询地址
        Address address = addressService.getById(order.getAddressId());
        if (address != null) {
            orderVO.setAddress(AddressVO.objToVo(address));
        }

        //关联查询商品规格
        ProductSKU productSKU = productSKUService.getById(order.getSkuId());
        if (productSKU != null) {
            orderVO.setProductSKUVO(ProductSKUVO.objToVo(productSKU));
        }

        //关联查询商品
        if (productSKU != null) {
            Product product = productService.getById(productSKU.getProductId());
            ProductMainVO productMainVO = new ProductMainVO();
            BeanUtil.copyProperties(product, productMainVO);
            orderVO.setProduct(productMainVO);
        }

        return orderVO;
    }

    /**
     * 分页获取订单封装
     *
     * @param orderPage
     * @param request
     * @return
     */
    @Override
    public Page<OrderVO> getOrderVOPage(Page<Order> orderPage, HttpServletRequest request) {
        // 获取当前页的订单记录
        List<Order> orderList = orderPage.getRecords();

        // 初始化返回的分页对象
        Page<OrderVO> orderVOPage = new Page<>(orderPage.getCurrent(), orderPage.getSize(), orderPage.getTotal());

        // 如果没有订单记录，直接返回
        if (CollUtil.isEmpty(orderList)) {
            return orderVOPage;
        }

        // 获取所有订单相关 ID
        List<Long> userIds = orderList.stream().map(Order::getUserId).distinct().collect(Collectors.toList());
        List<Long> addressIds = orderList.stream().map(Order::getAddressId).distinct().collect(Collectors.toList());
        List<Long> skuIds = orderList.stream().map(Order::getSkuId).distinct().collect(Collectors.toList());

        // 批量查询用户信息
        Map<Long, UserVO> userVOMap = userService.listByIds(userIds).stream()
                .collect(Collectors.toMap(User::getId, user -> {
                    UserVO userVO = new UserVO();
                    BeanUtil.copyProperties(user, userVO);
                    return userVO;
                }));

        // 批量查询地址信息
        Map<Long, AddressVO> addressVOMap = addressService.listByIds(addressIds).stream()
                .collect(Collectors.toMap(Address::getId, AddressVO::objToVo));

        // 批量查询商品规格信息
        Map<Long, ProductSKUVO> productSKUVOMap = productSKUService.listByIds(skuIds).stream()
                .collect(Collectors.toMap(ProductSKU::getId, ProductSKUVO::objToVo));

        // 获取所有商品 ID
        List<Long> productIds = productSKUVOMap.values().stream()
                .map(ProductSKUVO::getProductId)
                .distinct()
                .collect(Collectors.toList());

        // 批量查询商品信息
        Map<Long, ProductMainVO> productMainVOMap = productService.listByIds(productIds).stream()
                .collect(Collectors.toMap(Product::getId, product -> {
                    ProductMainVO productMainVO = new ProductMainVO();
                    BeanUtil.copyProperties(product, productMainVO);
                    return productMainVO;
                }));

        // 填充部分
        List<OrderVO> orderVOList = orderList.parallelStream().map(order -> {
            OrderVO orderVO = OrderVO.objToVo(order);

            // 直接从 Map 获取填充，减少 Map 访问次数
            orderVO.setUser(userVOMap.get(order.getUserId()));
            orderVO.setAddress(addressVOMap.get(order.getAddressId()));
            orderVO.setProductSKUVO(productSKUVOMap.get(order.getSkuId()));

            // 通过 SKU 找到对应的商品
            ProductSKUVO skuVO = productSKUVOMap.get(order.getSkuId());
            if (skuVO != null) {
                orderVO.setProduct(productMainVOMap.get(skuVO.getProductId()));
            }
            return orderVO;
        }).collect(Collectors.toList());

        // 设置填充后的数据
        orderVOPage.setRecords(orderVOList);
        return orderVOPage;
    }

    @Override
    @Transactional
    public long addOrder(OrderAddRequest orderAddRequest, HttpServletRequest request) {
        Order order = new Order();
        BeanUtils.copyProperties(orderAddRequest, order);
        // 数据校验
        validOrder(order, true);
        if (orderAddRequest.getUserId() == null) {
            User loginUser = userService.getLoginUser(request);
            order.setUserId(loginUser.getId());
        }
        // 计算总金额
        BigDecimal price = productSKUService.getById(order.getSkuId()).getPrice();
        BigDecimal quantity = BigDecimal.valueOf(order.getQuantity());
        BigDecimal originalPrice = price.multiply(quantity).setScale(2, RoundingMode.HALF_EVEN);
        order.setOriginalPrice(originalPrice);

        //初始化优惠金额为0
        BigDecimal discountAmount = BigDecimal.ZERO;

        // 查询是否有此优惠券
        if (orderAddRequest.getCouponId() != null) {
            Long couponId = orderAddRequest.getCouponId();
            UserCoupon userCoupon = userCouponService.query().eq("couponId", couponId)
                    .eq("userId", order.getUserId())
                    .eq("status", UserCouponStatusEnum.UNUSED.getValue())
                    .one();
            if (userCoupon == null) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "优惠券不存在或已被使用");
            }
            // 获取优惠券规则
            Coupon coupon = couponService.getById(couponId);
            if (coupon.getType().equals(CouponTypeEnum.FIXED.getValue())) {
                // 固定金额优惠
                discountAmount = coupon.getDiscountAmount()
                        .setScale(2, RoundingMode.HALF_EVEN);

                // 确保优惠金额不超过原价
                if (discountAmount.compareTo(originalPrice) > 0) {
                    discountAmount = originalPrice;
                }
            } else if (coupon.getType().equals(CouponTypeEnum.PERCENT.getValue())) {
                BigDecimal discountRate = coupon.getDiscountAmount()
                        .divide(BigDecimal.valueOf(100), 4, RoundingMode.HALF_EVEN);
                discountAmount = originalPrice.multiply(discountRate)
                        .setScale(2, RoundingMode.HALF_EVEN);

                // 折扣金额不能超过原价
                discountAmount = discountAmount.min(originalPrice);
            }
            // 计算实际支付金额
            BigDecimal totalAmount = originalPrice.subtract(discountAmount)
                    .max(BigDecimal.ZERO)
                    .setScale(2, RoundingMode.HALF_EVEN);
            // 设置金额字段
            order.setOriginalPrice(originalPrice);
            order.setDiscountAmount(discountAmount);
            order.setTotalPrice(totalAmount);

            // userCoupon表更新
            userCoupon.setOrderId(order.getId());
            // todo 锁定优惠券（使用分布式锁）
            userCoupon.setStatus(UserCouponStatusEnum.USED.getValue());
            if (!userCouponService.updateById(userCoupon)) {
                throw new BusinessException(ErrorCode.OPERATION_ERROR, "优惠券使用失败");
            }
        } else {
            order.setTotalPrice(originalPrice);
        }

        // 设置状态为待支付
        order.setOrderStatus(OrderStatusEnum.PENDING.getValue());
        order.setPaymentStatus(OrderPayStatusEnum.PENDING.getValue());
        // 写入数据库
        boolean result = save(order);
        ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR);
        // 扣减库存
        productSKUService.update(new UpdateWrapper<ProductSKU>().setSql("stock = stock - " + order.getQuantity()).eq("id", order.getSkuId()));
        updateRedisDashboard();

        //订单时间写入redis,用于超时取消订单
        long timeMillis = System.currentTimeMillis();
        stringRedisTemplate.opsForZSet().add(
                ORDER_TIMEOUT_KEY,
                order.getId().toString(),
                timeMillis
        );
        return order.getId();
    }

    //订单支付
    @Override
    public Boolean payOrder(OrderOperationRequest orderOperationRequest, HttpServletRequest request) {
        Order order = getOrderInfo(orderOperationRequest, request);
        // 若订单状态非 `pending` 或支付状态非 `pending`，抛出异常 `"订单无法支付"`
        if (!OrderStatusEnum.PENDING.getValue().equals(order.getOrderStatus())
                || !OrderPayStatusEnum.PENDING.getValue().equals(order.getPaymentStatus())) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "订单无法支付");
        }

        // 模拟调用第三方支付接口（如支付宝、微信），获取支付结果
        boolean payResult = getPayResult(order);

        // 更新状态
        if (payResult) {
            order.setOrderStatus(OrderStatusEnum.PAID.getValue());
            order.setPaymentStatus(OrderPayStatusEnum.SUCCESS.getValue());
            order.setPaymentTime(new Date());
        } else {
            order.setPaymentStatus(OrderPayStatusEnum.FAILED.getValue());
        }

        // 更新订单状态
        boolean b = updateById(order);
        if (b) {
            updateSalesInRedis(order);
        }
        updateRedisDashboardMoney(order);
        // 消息通知
        asyncMessageSender.sendOrderMessage("订单编号：" + order.getId() + "，订单支付成功");
        // 修改redis中的订单超时取消时间
        removeRedisZSetOrder(order);

        return b;
    }

    @Override
    public Boolean confirmReceipt(OrderOperationRequest orderOperationRequest, HttpServletRequest request) {
        Order order = getOrderInfo(orderOperationRequest, request);
        // 若订单状态非 `shipped` 或支付状态非 `success`，抛出异常 `"当前状态无法确认收货"`
        if (!OrderStatusEnum.SHIPPED.getValue().equals(order.getOrderStatus())
                || !OrderPayStatusEnum.SUCCESS.getValue().equals(order.getPaymentStatus())) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "当前状态无法确认收货");
        }
        // 更新状态
        order.setOrderStatus(OrderStatusEnum.COMPLETED.getValue());
        // 保存订单
        return updateById(order);
    }

    // 取消订单
    @Override
    @Transactional
    public Boolean cancelOrder(OrderOperationRequest orderOperationRequest, HttpServletRequest request) {
        Order order = getOrderInfo(orderOperationRequest, request);

        /* 允许取消的三种场景：
         * 1. 待支付 + 支付未完成（pending/failed）
         * 2. 已支付 + 支付成功
         * 3. 已发货 + 支付成功
         */
        boolean isCancelable =
                (OrderStatusEnum.PENDING.getValue().equals(order.getOrderStatus())
                        && (OrderPayStatusEnum.PENDING.getValue().equals(order.getPaymentStatus())
                        || OrderPayStatusEnum.FAILED.getValue().equals(order.getPaymentStatus())));
                        /*|| (OrderStatusEnum.PAID.getValue().equals(order.getOrderStatus())
                        && OrderPayStatusEnum.SUCCESS.getValue().equals(order.getPaymentStatus()))
                        || (OrderStatusEnum.SHIPPED.getValue().equals(order.getOrderStatus())
                        && OrderPayStatusEnum.SUCCESS.getValue().equals(order.getPaymentStatus()));*/

        if (!isCancelable) {
            log.warn("非法取消请求，订单ID：{}，当前状态：{}/{}",
                    order.getId(), order.getOrderStatus(), order.getPaymentStatus());
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "当前状态无法取消");
        }

        // 更新状态
        order.setOrderStatus(OrderStatusEnum.CANCELLED.getValue());

        // 更新库存
        productSKUService.update(new UpdateWrapper<ProductSKU>().setSql("stock = stock + " + order.getQuantity()).eq("id", order.getSkuId()));

        // 修改redis中的订单超时取消时间
        removeRedisZSetOrder(order);

        //保存订单
        return updateById(order);
    }
    // 修改redis中的订单超时取消时间
    private void removeRedisZSetOrder(Order order) {
        stringRedisTemplate.opsForZSet().remove(
                ORDER_TIMEOUT_KEY,
                order.getId().toString()
        );
    }

    // 退款
    @Override
    public Boolean refundOrder(OrderOperationRequest orderOperationRequest, HttpServletRequest request) {
        Order order = getOrderInfo(orderOperationRequest, request);
        // 订单状态必须为success
        if (!OrderStatusEnum.PAID.getValue().equals(order.getOrderStatus())) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "当前状态无法退款");
        }
        // 订单状态未支付，不允许退款
        if (OrderStatusEnum.PENDING.getValue().equals(order.getPaymentStatus())) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "订单状态未支付，无需退款");
        }
        // 订单状态已取消，不允许退款
        if (OrderStatusEnum.CANCELLED.getValue().equals(order.getPaymentStatus())) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "订单状态已取消，无需退款");
        }
        // 订单状态已退款，不允许退款
        if (OrderStatusEnum.REFUNDED.getValue().equals(order.getPaymentStatus())) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "订单状态已退款，无需重复操作");
        }
        // TODO 判断退款时效性

        // 已发货订单，物流拦截校验
        //- 若订单状态为shipped，需先调用物流接口拦截包裹。
        //- 若物流拦截失败，返回错误 "物流拦截失败，无法退款"
        if (OrderStatusEnum.SHIPPED.getValue().equals(order.getOrderStatus())) {
            // TODO: 调用物流拦截接口
            // - 若物流拦截失败，返回错误 "物流拦截失败，无法退款"
            if (!getInterceptResult(order)) {
                throw new BusinessException(ErrorCode.OPERATION_ERROR, "物流拦截失败，无法退款");
            }
        }
        // 已完成订单管理员审核
        if (userService.isAdmin(request)) {
            // 管理员审核   若管理员审核不通过，返回错误 "管理员审核不通过，无法退款"
            if (!getAdminResult(order)) {
                throw new BusinessException(ErrorCode.OPERATION_ERROR, "管理员审核不通过，无法退款");
            }
        }
        // 已支付，但未发货，直接退款
        if (OrderStatusEnum.PAID.getValue().equals(order.getOrderStatus())) {
            order.setPaymentStatus(OrderPayStatusEnum.REFUNDED.getValue());
            order.setOrderStatus(OrderStatusEnum.REFUNDED.getValue());
            return this.updateById(order);
        }
        // 提醒用户退款已申请
        return Boolean.FALSE;
    }

    // 查询订单
    @Override
    public Page<OrderVO> listOrderVOByPage(OrderAllQueryRequest orderAllQueryRequest, HttpServletRequest request) {
        if (orderAllQueryRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }

        // 分页查询 OrderAllQueryResult
        Page<OrderAllQueryResult> page = new Page<>(orderAllQueryRequest.getCurrent(), orderAllQueryRequest.getPageSize());
        Page<OrderAllQueryResult> orderAllQueryResultPage = orderMapper.queryOrders(page, orderAllQueryRequest);

        // 转换为 OrderVO
        List<OrderVO> orderVOList = orderAllQueryResultPage.getRecords().stream()
                .map(orderAllQueryResult -> {
                    OrderVO orderVO = new OrderVO();
                    // 使用 Optional 防止空指针
                    orderVO.setId(orderAllQueryResult.getOrderId());
                    orderVO.setUserId(orderAllQueryResult.getUserId());

                    // 转换 UserVO
                    orderVO.setUser(Optional.ofNullable(orderAllQueryResult.getUserId()).map(userName -> {
                        UserVO userVO = new UserVO();
                        userVO.setUserName(orderAllQueryResult.getUserName());
                        userVO.setPhone(orderAllQueryResult.getPhone());
                        userVO.setEmail(orderAllQueryResult.getEmail());
                        userVO.setId(orderAllQueryResult.getUserId());
                        return userVO;
                    }).orElse(new UserVO()));  // 空值时给 UserVO 赋空对象

                    // 转换 AddressVO
                    orderVO.setAddress(Optional.ofNullable(orderAllQueryResult.getAddressName()).map(addressName -> {
                        AddressVO addressVO = new AddressVO();
                        addressVO.setAddressName(addressName);
                        addressVO.setId(orderAllQueryResult.getAddressId());
                        return addressVO;
                    }).orElse(new AddressVO()));  // 空值时给 AddressVO 赋空对象

                    // 转换 ProductMainVO
                    orderVO.setProduct(Optional.ofNullable(orderAllQueryResult.getProductName()).map(productName -> {
                        ProductMainVO productVO = new ProductMainVO();
                        productVO.setName(productName);
                        productVO.setCategoryId(orderAllQueryResult.getCategoryId());
                        productVO.setId(orderAllQueryResult.getProductId());
                        return productVO;
                    }).orElse(new ProductMainVO()));  // 空值时给 ProductMainVO 赋空对象

                    // 设置其他字段
                    orderVO.setAddressId(orderAllQueryResult.getAddressId());
                    orderVO.setSkuId(orderAllQueryResult.getSkuId());
                    orderVO.setProductSKUVO(new ProductSKUVO());
                    orderVO.getProductSKUVO().setId(orderAllQueryResult.getSkuId());
                    orderVO.setQuantity(orderAllQueryResult.getQuantity());
                    orderVO.setTotalPrice(orderAllQueryResult.getTotalPrice());
                    orderVO.setOrderStatus(orderAllQueryResult.getOrderStatus());
                    orderVO.setPaymentStatus(orderAllQueryResult.getPaymentStatus());
                    orderVO.setPaymentTime(orderAllQueryResult.getPaymentTime());
                    orderVO.setCreateTime(orderAllQueryResult.getCreateTime());
                    return orderVO;
                })
                .collect(Collectors.toList());

        // 将查询结果转换为分页后的对象
        Page<OrderVO> orderVOPage = new Page<>();
        orderVOPage.setCurrent(orderAllQueryResultPage.getCurrent());
        orderVOPage.setSize(orderAllQueryResultPage.getSize());
        orderVOPage.setTotal(orderAllQueryResultPage.getTotal());
        orderVOPage.setRecords(orderVOList);

        return orderVOPage;
    }

    // 发货
    @Override
    public Boolean deliverOrder(OrderOperationRequest orderOperationRequest, HttpServletRequest request) {
        Order order = getOrderInfo(orderOperationRequest, request);
        // 判断订单状态与支付状态
        // 订单状态为paid、支付状态为success 允许发货
        if (OrderStatusEnum.PAID.getValue().equals(order.getOrderStatus()) && OrderPayStatusEnum.SUCCESS.getValue().equals(order.getPaymentStatus())) {
            // 订单状态为paid、支付状态为success 允许发货
            order.setOrderStatus(OrderStatusEnum.SHIPPED.getValue());

            stringRedisTemplate.opsForHash().increment(DASHBOARD_KEY, "pendingShipment", -1);
            // TODO 调用物流服务
            return this.updateById(order);
        }
        throw new BusinessException(ErrorCode.OPERATION_ERROR, "请检查订单状态，该订单无法发货");
    }

    /**
     * 批量添加订单并支付
     *
     * @param orderAddBatchRequest 订单批量添加请求
     * @param request              HTTP请求
     * @return 操作结果
     */
    @Transactional
    @Override
    public Boolean addOrderBatch(OrderAddBatchRequest orderAddBatchRequest, HttpServletRequest request) {
        // 参数校验和用户权限验证
        validateRequest(orderAddBatchRequest);
        User loginUser = userService.getLoginUser(request);
        Long userId = determineUserId(orderAddBatchRequest, loginUser);

        // 获取并验证购物车数据
        List<Long> cartIds = orderAddBatchRequest.getCartIds();
        List<Cart> cartList = getAndValidateCarts(cartIds);

        // 获取并验证商品规格
        List<Long> skuIds = extractSkuIds(cartList);
        List<ProductSKU> productSKUList = getAndValidateSkus(skuIds);

        // 获取并验证商品信息
        List<Product> productList = getAndValidateProducts(productSKUList);

        // 创建订单列表
        List<Order> orderList;
        if (orderAddBatchRequest.getCouponId() == null) {
            orderList = createOrders(cartList, productSKUList, userId, orderAddBatchRequest.getAddressId());
        } else {
            orderList = createOrders(cartList, productSKUList, userId, orderAddBatchRequest.getAddressId(), orderAddBatchRequest.getCouponId());
        }

        // 批量保存订单
        saveOrders(orderList);

        // 处理支付并更新订单状态
        processPayments(orderList);

        // 扣减库存
        processStockReduction(orderList);

        // 更新购物车
        deleteCarts(cartIds);

        // 更新redis销量
        orderList.forEach(this::updateSalesInRedis);

        updateRedisDashboardMoney(orderList);
        // 发送消息
        asyncMessageSender.sendOrderMessage("有新的订单支付：" + orderList.size() + "个");

        return true;
    }

    // 更新redis销量
    @Async("taskExecutor")
    @Override
    public void updateSalesInRedis(Order order) {
        Long skuId = order.getSkuId();
        int quantity = order.getQuantity();

        // 获取商品 ID
        ProductSKU sku = productSKUService.getById(skuId);
        Long productId = sku.getProductId();

        // 更新 SKU 销量
        String skuSalesKey = SKU_SALES_STATISTIC_KEY + productId;
        stringRedisTemplate.opsForHash().increment(skuSalesKey, skuId.toString(), quantity);

        // 更新商品总销量
        stringRedisTemplate.opsForZSet().incrementScore(PRODUCT_SALES_STATISTIC_KEY, productId.toString(), quantity);
    }

    @Override
    public OrderPriceVO getOrderPrice(Long couponId, Integer money) {
        BigDecimal originalPrice = new BigDecimal(money);
        BigDecimal discountAmount = BigDecimal.ZERO;
        // 获取优惠券规则
        Coupon coupon = couponService.getById(couponId);
        if (coupon.getType().equals(CouponTypeEnum.FIXED.getValue())) {
            // 固定金额优惠
            discountAmount = coupon.getDiscountAmount()
                    .setScale(2, RoundingMode.HALF_EVEN);

            // 确保优惠金额不超过原价
            if (discountAmount.compareTo(originalPrice) > 0) {
                discountAmount = originalPrice;
            }
        } else if (coupon.getType().equals(CouponTypeEnum.PERCENT.getValue())) {
            BigDecimal discountRate = coupon.getDiscountAmount()
                    .divide(BigDecimal.valueOf(100), 4, RoundingMode.HALF_EVEN);
            discountAmount = originalPrice.multiply(discountRate)
                    .setScale(2, RoundingMode.HALF_EVEN);

            // 折扣金额不能超过原价
            discountAmount = discountAmount.min(originalPrice);
        }
        // 计算实际支付金额
        BigDecimal totalAmount = originalPrice.subtract(discountAmount)
                .max(BigDecimal.ZERO)
                .setScale(2, RoundingMode.HALF_EVEN);
        // 设置金额字段
        OrderPriceVO priceVO = new OrderPriceVO();
        priceVO.setOriginalPrice(originalPrice);
        priceVO.setDiscountAmount(discountAmount);
        priceVO.setTotalPrice(totalAmount);

        return priceVO;
    }

    /**
     * 删除购物车数据
     */
    private void deleteCarts(List<Long> cartIds) {
        int i = cartMapper.deleteBatchIds(cartIds);
        log.info("购物车删除结果，已删除数量: {}, 预期删除数量: {}", i, cartIds.size());
        if (i != cartIds.size()) {
            log.error("购物车删除失败，ids: {}", cartIds);
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "购物车更新失败");
        }
    }


    /**
     * 批量处理库存扣减
     *
     * @param orderList 订单列表
     *                  TODO 考虑高并发
     */
    @Transactional
    public void processStockReduction(List<Order> orderList) {
        // 按SKU ID分组，统计每个SKU需要扣减的总数量
        Map<Long, Integer> skuReductionMap = orderList.stream()
                .collect(Collectors.groupingBy(
                        Order::getSkuId,
                        Collectors.summingInt(Order::getQuantity)
                ));

        // 批量查询SKU信息
        List<Long> skuIds = new ArrayList<>(skuReductionMap.keySet());
        List<ProductSKU> skuList = productSKUService.listByIds(skuIds);
        if (skuList.size() != skuIds.size()) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "部分商品规格不存在");
        }

        // 检查库存并扣减
        skuList.forEach(sku -> {
            int reductionQuantity = skuReductionMap.get(sku.getId());
            if (sku.getStock() < reductionQuantity) {
                throw new BusinessException(ErrorCode.OPERATION_ERROR,
                        "商品规格ID: " + sku.getId() + " 库存不足，当前库存: " + sku.getStock() + "，需要扣减: " + reductionQuantity);
            }
            sku.setStock(sku.getStock() - reductionQuantity);
        });

        // 批量更新库存
        if (!productSKUService.updateBatchById(skuList)) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "库存扣减失败");
        }
    }

    /**
     * 验证请求参数合法性
     */
    private void validateRequest(OrderAddBatchRequest request) {
        if (request.getCartIds() == null || request.getCartIds().isEmpty()) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "购物车ID不能为空");
        }
        if (request.getAddressId() == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "收货地址不能为空");
        }
    }

    /**
     * 确定最终用户ID并进行权限校验
     */
    private Long determineUserId(OrderAddBatchRequest request, User loginUser) {
        Long requestUserId = request.getUserId();
        if (requestUserId == null) {
            return loginUser.getId();
        }
        if (!requestUserId.equals(loginUser.getId()) && !UserRoleEnum.ADMIN.getValue().equals(loginUser.getUserRole())) {
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "无权操作他人订单");
        }
        return requestUserId;
    }

    /**
     * 获取并验证购物车数据
     */
    private List<Cart> getAndValidateCarts(List<Long> cartIds) {
        List<Cart> cartList = cartService.listByIds(cartIds);
        if (cartList.size() != cartIds.size()) {
            Set<Long> foundIds = cartList.stream().map(Cart::getId).collect(Collectors.toSet());
            String missingIds = cartIds.stream()
                    .filter(id -> !foundIds.contains(id))
                    .map(String::valueOf)
                    .collect(Collectors.joining(", "));
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "购物车项不存在: " + missingIds);
        }
        return cartList;
    }

    /**
     * 提取商品规格ID列表
     */
    private List<Long> extractSkuIds(List<Cart> cartList) {
        return cartList.stream()
                .map(Cart::getSkuId)
                .collect(Collectors.toList());
    }

    /**
     * 获取并验证商品规格
     */
    private List<ProductSKU> getAndValidateSkus(List<Long> skuIds) {
        List<ProductSKU> skuList = productSKUService.listByIds(skuIds);
        validateSkus(skuIds, skuList);
        skuList.forEach(sku -> {
            if (!ProductStatusEnum.ACTIVE.getValue().equals(sku.getStatus())) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR, productService.getById(sku.getProductId()).getName() + " 商品规格已下架");
            }
        });
        return skuList;
    }

    /**
     * 验证商品规格是否存在
     */
    private void validateSkus(List<Long> requiredIds, List<ProductSKU> foundSkus) {
        if (foundSkus.size() != requiredIds.size()) {
            Set<Long> foundIds = foundSkus.stream().map(ProductSKU::getId).collect(Collectors.toSet());
            String missingIds = requiredIds.stream()
                    .filter(id -> !foundIds.contains(id))
                    .map(String::valueOf)
                    .collect(Collectors.joining(", "));
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "商品规格不存在: " + missingIds);
        }
    }

    /**
     * 获取并验证商品信息
     */
    private List<Product> getAndValidateProducts(List<ProductSKU> skuList) {
        List<Long> productIds = skuList.stream()
                .map(ProductSKU::getProductId)
                .distinct()
                .collect(Collectors.toList());
        List<Product> productList = productService.listByIds(productIds);
        validateProducts(productIds, productList);
        productList.forEach(product -> {
            if (!ProductStatusEnum.ACTIVE.getValue().equals(product.getStatus())) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR, product.getName() + " 商品已下架");
            }
        });
        return productList;
    }

    /**
     * 验证商品是否存在
     */
    private void validateProducts(List<Long> requiredIds, List<Product> foundProducts) {
        if (foundProducts.size() != requiredIds.size()) {
            Set<Long> foundIds = foundProducts.stream().map(Product::getId).collect(Collectors.toSet());
            String missingIds = requiredIds.stream()
                    .filter(id -> !foundIds.contains(id))
                    .map(String::valueOf)
                    .collect(Collectors.joining(", "));
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "商品不存在: " + missingIds);
        }
    }

    /**
     * 创建订单列表
     */
    private List<Order> createOrders(List<Cart> carts, List<ProductSKU> skus, Long userId, Long addressId) {
        Map<Long, ProductSKU> skuMap = skus.stream()
                .collect(Collectors.toMap(ProductSKU::getId, Function.identity()));

        return carts.stream().map(cart -> {
            ProductSKU sku = skuMap.get(cart.getSkuId());
            BigDecimal totalPrice = sku.getPrice().multiply(BigDecimal.valueOf(cart.getQuantity()));

            Order order = new Order();
            order.setUserId(userId);
            order.setAddressId(addressId);
            order.setSkuId(cart.getSkuId());
            order.setQuantity(cart.getQuantity());
            order.setTotalPrice(totalPrice);
            order.setOrderStatus(OrderStatusEnum.PENDING.getValue());
            order.setPaymentStatus(OrderPayStatusEnum.PENDING.getValue());
            return order;
        }).collect(Collectors.toList());
    }

    /**
     * 创建订单列表(使用优惠券)
     */
    private List<Order> createOrders(List<Cart> carts, List<ProductSKU> skus, Long userId, Long addressId, Long couponId) {
        Map<Long, ProductSKU> skuMap = skus.stream()
                .collect(Collectors.toMap(ProductSKU::getId, Function.identity()));

        // 1. 校验优惠券有效性
        Coupon coupon = couponService.getById(couponId);
        if (coupon == null) { // 原代码条件写反了，这里修正为 coupon == null
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "无此优惠券");
        }
        Date now = new Date();
        if (coupon.getEndTime().before(now)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "优惠券已过期");
        }
        if (coupon.getStartTime().after(now)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "优惠券未到使用时间");
        }

        // 2. 检查用户是否拥有未使用的优惠券
        UserCoupon userCoupon = userCouponService.query()
                .eq("userId", userId)
                .eq("couponId", couponId)
                .eq("status", UserCouponStatusEnum.UNUSED.getValue())
                .one();
        if (userCoupon == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "优惠券已被使用或不存在");
        }

        // 3. 计算总原价（所有购物车项的总和）
        BigDecimal totalOriginalPrice = carts.stream()
                .map(cart -> {
                    ProductSKU sku = skuMap.get(cart.getSkuId());
                    return sku.getPrice().multiply(BigDecimal.valueOf(cart.getQuantity()));
                })
                .reduce(BigDecimal.ZERO, BigDecimal::add);

        // 4. 根据优惠券类型计算总优惠金额
        BigDecimal totalDiscount = calculateTotalDiscount(coupon, totalOriginalPrice);

        // 5. 分摊优惠金额到每个订单
        List<BigDecimal> discountsPerOrder = distributeDiscounts(
                carts, skuMap, coupon.getType(), totalOriginalPrice, totalDiscount
        );

        // 6. 生成订单列表
        AtomicInteger index = new AtomicInteger(0);

        // 7.修改优惠券状态为已使用
        Long id = userCoupon.getId();
        userCouponService.update()
                .set("status", UserCouponStatusEnum.USED.getValue())
                .eq("id", id)
                .update();
        return carts.stream().map(cart -> {
            ProductSKU sku = skuMap.get(cart.getSkuId());
            BigDecimal originalPrice = sku.getPrice().multiply(BigDecimal.valueOf(cart.getQuantity()));

            // 获取当前订单的优惠金额
            BigDecimal discount = discountsPerOrder.get(index.getAndIncrement());

            Order order = new Order();
            order.setUserId(userId);
            order.setAddressId(addressId);
            order.setSkuId(cart.getSkuId());
            order.setQuantity(cart.getQuantity());
            order.setOriginalPrice(originalPrice);
            order.setDiscountAmount(discount);
            order.setTotalPrice(originalPrice.subtract(discount));
//            order.setCouponId(couponId);
            order.setOrderStatus(OrderStatusEnum.PENDING.getValue());
            order.setPaymentStatus(OrderPayStatusEnum.PENDING.getValue());
            return order;
        }).collect(Collectors.toList());
    }
    // 计算总优惠金额
    private BigDecimal calculateTotalDiscount(Coupon coupon, BigDecimal totalOriginalPrice) {
        if (CouponTypeEnum.FIXED.getValue().equals(coupon.getType())) {
            // 固定金额：直接取券面值，但不能超过总原价
            return coupon.getDiscountAmount().min(totalOriginalPrice);
        } else if (CouponTypeEnum.PERCENT.getValue().equals(coupon.getType())) {
            // 百分比折扣：总原价 * 折扣率
            BigDecimal discountRate = coupon.getDiscountAmount().divide(BigDecimal.valueOf(100), 4, RoundingMode.HALF_EVEN);
            return totalOriginalPrice.multiply(discountRate).setScale(2, RoundingMode.HALF_EVEN);
        }
        return BigDecimal.ZERO;
    }

    // 分摊优惠金额到每个订单
    private List<BigDecimal> distributeDiscounts(
            List<Cart> carts,
            Map<Long, ProductSKU> skuMap,
            String couponType,
            BigDecimal totalOriginalPrice,
            BigDecimal totalDiscount
    ) {
        List<BigDecimal> discounts = new ArrayList<>();

        if (CouponTypeEnum.FIXED.getValue().equals(couponType)) {
            // 固定金额：按订单原价比例分摊
            BigDecimal remainingDiscount = totalDiscount;
            for (int i = 0; i < carts.size(); i++) {
                Cart cart = carts.get(i);
                BigDecimal itemPrice = skuMap.get(cart.getSkuId()).getPrice()
                        .multiply(BigDecimal.valueOf(cart.getQuantity()));

                // 最后一个订单承担剩余优惠金额（解决小数精度问题）
                if (i == carts.size() - 1) {
                    discounts.add(remainingDiscount);
                } else {
                    BigDecimal ratio = itemPrice.divide(totalOriginalPrice, 10, RoundingMode.HALF_EVEN);
                    BigDecimal discount = totalDiscount.multiply(ratio).setScale(2, RoundingMode.HALF_EVEN);
                    discounts.add(discount);
                    remainingDiscount = remainingDiscount.subtract(discount);
                }
            }
        } else {
            // 百分比折扣：每个订单独立计算
            carts.forEach(cart -> {
                BigDecimal itemPrice = skuMap.get(cart.getSkuId()).getPrice()
                        .multiply(BigDecimal.valueOf(cart.getQuantity()));
                BigDecimal discount = itemPrice.multiply(totalDiscount.divide(totalOriginalPrice, 4, RoundingMode.HALF_EVEN))
                        .setScale(2, RoundingMode.HALF_EVEN);
                discounts.add(discount);
            });
        }
        return discounts;
    }

    /**
     * 保存订单列表
     */
    @Transactional
    public void saveOrders(List<Order> orders) {
        if (!this.saveBatch(orders)) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "订单生成失败");
        }
    }

    /**
     * 处理支付并更新订单状态
     */
    @Transactional
    public void processPayments(List<Order> orders) {
        orders.forEach(order -> {
            if (!getPayResult(order)) {
                throw new BusinessException(ErrorCode.OPERATION_ERROR, "支付失败，订单号: " + order.getId());
            }
            order.setOrderStatus(OrderStatusEnum.PAID.getValue());
            order.setPaymentStatus(OrderPayStatusEnum.SUCCESS.getValue());
        });

        if (!this.updateBatchById(orders)) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "订单状态更新失败");
        }
    }

    /**
     * 模拟支付操作
     */
    private boolean getPayResult(Order order) {
        try {
            Thread.sleep(1500);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        return true;
    }

    // 模拟拦截物流
    private boolean getInterceptResult(Order order) {
        // TODO 管理员审核
        return true;
    }

    // 管理员审核
    private boolean getAdminResult(Order order) {
        // TODO 管理员审核
        return true;
    }

    // 通用获取订单信息
    private Order getOrderInfo(OrderOperationRequest orderOperationRequest, HttpServletRequest request) {
        Long id = orderOperationRequest.getId();
        Order order = this.getById(id);
        if (order == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "订单不存在");
        }

        // 仅本人或管理员操作
        User loginUser = userService.getLoginUser(request);
        if (!order.getUserId().equals(loginUser.getId()) && !userService.isAdmin(request)) {
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
        }
        return order;
    }

    // 异步
    @Async("taskExecutor")
    public void updateRedisDashboard() {
        stringRedisTemplate.opsForHash().increment(DASHBOARD_KEY, "todayOrders", 1);
    }

    // 异步
    @Async("taskExecutor")
    public void updateRedisDashboardMoney(Order order) {
        stringRedisTemplate.opsForHash().increment(DASHBOARD_KEY, "pendingShipment", 1);
        String currentVal = (String) stringRedisTemplate.opsForHash().get(DASHBOARD_KEY, "todaySales");
        BigDecimal newVal = new BigDecimal(currentVal != null ? currentVal : "0").add(order.getTotalPrice());
        stringRedisTemplate.opsForHash().put(DASHBOARD_KEY, "todaySales", newVal.toPlainString());
    }

    @Async("taskExecutor")
    public void updateRedisDashboardMoney(List<Order> orders) {
        int size = orders.size();
        stringRedisTemplate.opsForHash().increment(DASHBOARD_KEY, "pendingShipment", size);
        // 列表总金额
        String currentVal = (String) stringRedisTemplate.opsForHash().get(DASHBOARD_KEY, "todaySales");
        BigDecimal totalPrice = orders.stream().map(Order::getTotalPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal newVal = new BigDecimal(currentVal != null ? currentVal : "0").add(totalPrice);
        stringRedisTemplate.opsForHash().put(DASHBOARD_KEY, "todaySales", newVal.toPlainString());

        stringRedisTemplate.opsForHash().increment(DASHBOARD_KEY, "todayOrders", size);
    }


}
